#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "database.h"
#include "../shared/log.h"
#include <pthread.h>

struct dbinfo info;
pthread_key_t mysql_key;

void setdbinfo(const struct dbinfo *p)
{
  strcpy(info.dbserver,p->dbserver);
  strcpy(info.dbuser,p->dbuser);
  strcpy(info.dbpass,p->dbpass);
  strcpy(info.default_database,p->default_database);
  info.dbport = p->dbport;
}

int connect_db()
{ 
   MYSQL *mysql = (MYSQL *)pthread_getspecific(mysql_key);
   char value = 1;
   
   //underline make programe segment error!!!so delete this.!!!!!!!
   //mysql_options(&mysql, MYSQL_OPT_RECONNECT, (char *)&value);
   if (mysql_real_connect(mysql,info.dbserver,info.dbuser,info.dbpass,info.default_database,info.dbport,NULL,CLIENT_MULTI_STATEMENTS|CLIENT_MULTI_RESULTS)){
      WRITE_DEBUG ("database connect sucessfully!pid:%d",getpid());
      mysql_real_query(mysql,"set names 'utf8'",strlen("set names 'utf8'"));
      //query_db("SET AUTOCOMMIT=1 ");
      return 0;
   }
   WRITE_ERROR("connect db failed!,%s",mysql_error(mysql));

   return 1;
   
}


MYSQL_RES *query_db(const char *sql)
{
 MYSQL *mysql = (MYSQL *)pthread_getspecific(mysql_key);
 if (!mysql) return NULL;
 WRITE_DEBUG((char *)sql);

  MYSQL_RES *res_ptr = NULL;
  int ret ;
  int times = 0;
__RETRY:
  ret =  mysql_real_query(mysql,sql,strlen(sql));
  if (ret != 0){
    const char *err = mysql_error(mysql);
    WRITE_ERROR("mysql_real_query failed,[%d]:%s,%s",ret,mysql_error(mysql),err);
    if (ret == 1 && strstr(err,"has gone away")){
       if (mysql) {
          close_db(mysql);
          mysql = mysql_init(NULL);
          pthread_setspecific(mysql_key,mysql);
          WRITE_ERROR("reinit mysql"); 
       }
       if (connect_db() == 0){
         if (times++>=3) {return NULL;}
         WRITE_DEBUG("Retry connect database successfully,goto RETRY"); 
         goto __RETRY;
       }
       else{
        WRITE_DEBUG("Retry connect database failed.");
       }   
    }
  }
  else{ 
    res_ptr = mysql_store_result(mysql);
  }
 
  WRITE_DEBUG("query_db() return");
  return res_ptr;
}

int exec_db_trans(const char *sql)
{
  MYSQL *mysql = (MYSQL *)pthread_getspecific(mysql_key);
  if (!mysql) return -1;
  WRITE_DEBUG((char *)sql);

  //int rows = 0;
  int ret = -1;
  int times = 0;
__RETRY:
  ret =  mysql_real_query(mysql,sql,strlen(sql));
  if (ret != 0){
    const char *err = mysql_error(mysql);
    WRITE_ERROR("mysql_real_query failed,[%d]:%s,%s",ret,mysql_error(mysql),sql);
    if (ret == 1 && strstr(err,"has gone away")){
       if (mysql) {
          close_db(mysql);
          mysql = mysql_init(NULL);
          pthread_setspecific(mysql_key,mysql);  
          WRITE_ERROR("reinit mysql");
       }
       if (connect_db() == 0){
         if (times++>=3) {return 1;}
         WRITE_DEBUG("Retry connect database successfully,goto RETRY");
         goto __RETRY;
       }
       else{
        WRITE_DEBUG("Retry connect database failed.");
       }
    }
  }
  else{
    //rows = mysql_affected_rows(mysql);
  }
  
  return ret;
}

int exec_db(const char *sql)
{
  MYSQL *mysql = (MYSQL *)pthread_getspecific(mysql_key);
  if (!mysql) return -1;
  WRITE_DEBUG((char *)sql);

  //int rows = 0;
  int ret = -1;
  int times = 0;
__RETRY:
  ret =  mysql_real_query(mysql,sql,strlen(sql));
  if (ret != 0){
    const char *err = mysql_error(mysql);
    WRITE_ERROR("mysql_real_query failed,[%d]:%s,%s",ret,mysql_error(mysql),sql);
    if (ret == 1 && strstr(err,"has gone away")){
       if (mysql) {
          close_db(mysql);
          mysql = mysql_init(NULL);
          pthread_setspecific(mysql_key,mysql);  
          WRITE_ERROR("reinit mysql");
       }
       if (connect_db() == 0){
         if (times++>=3) {return 1;}
         WRITE_DEBUG("Retry connect database successfully,goto RETRY"); 
         goto __RETRY;
       }
       else{
        WRITE_DEBUG("Retry connect database failed.");
       }
    }
    mysql_real_query(mysql,"ROLLBACK",strlen("ROLLBACK"));
  }
  else{
    //rows = mysql_affected_rows(mysql);
    mysql_real_query(mysql,"COMMIT",strlen("COMMIT"));
  }
  
  WRITE_DEBUG("%d rows affected!",(ret == 0)?1:0);
  return ret;  
}


void query_show(MYSQL_RES *res_ptr)
{
  MYSQL_ROW sqlrow ;
  MYSQL_FIELD *fields;
  unsigned int numfields;
  
  numfields = mysql_num_fields(res_ptr);
  fields = mysql_fetch_fields(res_ptr);
  int i;
  while (sqlrow = mysql_fetch_row(res_ptr)){
    for ( i=0;i<numfields;i++)
       printf ("\n%s : %s \n",fields[i].name,sqlrow[i]?sqlrow[i]:"NULL");
  }

  mysql_free_result(res_ptr);
}

void close_db()
{
  MYSQL *mysql = (MYSQL *)pthread_getspecific(mysql_key);

  mysql_close(mysql);
  WRITE_DEBUG("pid:%d,pthreadid:%x,close_db called! ",getpid(),(unsigned int)pthread_self());
}
